﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace TaskBasedSchedule.Core
{
    public class Roles
    {
        #region Fields

        private ReaderWriterLock _syncLocker;
        private Dictionary<int, Role> _idRoleDic;

        #endregion


        #region Properties

        public Role this[int id]
        {
            get
            {
                throw new System.NotImplementedException();
            }
        }

        #endregion

        #region Public Functions

        public void AddRole(string name, string authorities)
        {
            if (!Framework.Instance.CurrentContext.CheckAuthority(BasicAuthoritiesEnum.ModifyRoles))
            {
                //TODO: Limit Authority Exception.
                return;
            }

            if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(authorities))
            {
                //TODO: Arguments invalid exception.
                return;
            }

            //Acquire a write lock.
            _syncLocker.AcquireWriterLock(Timeout.Infinite);

            int id;
            try
            {
                switch (Framework.Instance.Database.WorkingDatabaseType)
                {
                    case DatabaseType.MsSql:
                        id = PrivateMsSqlAddRole(name, authorities);
                        break;
                    default:
                        _syncLocker.ReleaseWriterLock();
                        //TODO: Throw unsupport exception.
                        return;
                }
            }
            catch
            {
                //Release locker.
                _syncLocker.ReleaseWriterLock();
                //Just throw the DatabaseOperationException.
                throw;
            }

            Role role = new Role();
            role.Id = id;
            role.Name = name;
            role.SetAuthorities(authorities);

            _syncLocker.ReleaseWriterLock();
        }

        public void AlterRoleName()
        {
            throw new System.NotImplementedException();
        }

        public void AlterRoleAuthorities()
        {
            throw new System.NotImplementedException();
        }

        public void RemoveRole()
        {
            throw new System.NotImplementedException();
        }

        #endregion


        #region Private Functions

        private void PrivateInitialize()
        {
            _syncLocker = new ReaderWriterLock();
            _idRoleDic = new Dictionary<int, Role>();

        }

        private void PrivateMsSqlLoadData()
        {
            Database database = Framework.Instance.Database.GetDatabase(DatabaseType.MsSql);

            var command = database.Connection.CreateCommand() as System.Data.SqlClient.SqlCommand;
            if(command==null)
            {
                //TODO: Throw exception.
                return;
            }

            command.CommandText = "SELECT * FROM [Roles]";

            System.Data.SqlClient.SqlDataReader reader = null;

            try
            {
                reader = command.ExecuteReader();
            }
            catch(Exception ex)
            {
                database.Close();
                ThrowHelper.DatabaseOperationError(ex);
            }

            try
            {
                Role role;
                while (reader.Read())
                {
                    role = new Role();
                    role.Id = reader.GetInt32(0);
                    role.Name = reader.GetString(1);
                    role.SetAuthorities(reader.GetString(2));
                }
            }
            catch(Exception ex)
            {
                reader.Close();
                database.Close();
                ThrowHelper.DatabaseOperationError(ex);
            }
        }

        private int PrivateMsSqlAddRole(string name,string authorities)
        {
            Database database;
            int id = -1;

            try
            {
                database = Framework.Instance.Database.GetDatabase(DatabaseType.MsSql);
            }
            catch
            {
                //Just throw the exception.
                throw;
            }

            System.Data.SqlClient.SqlCommand cmd = database.Connection.CreateCommand() as System.Data.SqlClient.SqlCommand;
            if (cmd == null)
            {
                //The database is not the type that it has been defined by user.
                //TODO: Throw exception.
                return -1;
            }

            cmd.CommandText = "INSERT INTO [Roles](`Name`,`Authorities`) VALUES (@name,@au)\nSELECT @@identity";
            cmd.Parameters.Add("name", System.Data.SqlDbType.NVarChar).Value = name;
            cmd.Parameters.Add("au", System.Data.SqlDbType.NVarChar).Value = authorities;

            try
            {
                id = Convert.ToInt32(cmd.ExecuteScalar());
            }
            catch
            {
                //Close database.
                database.Close();
                //Just throw the exception.
                throw;
            }

            return id;
        }

        #endregion



    }
}